﻿//
// File: ReportingService.cs
//
// Purpose:  implements simple logging functionality.
//
// Author: MotherHacker @ cachecleaner.codeplex.com


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Reporting
{

    public class LogEntry
    {
        public DateTime EventTime;
        public string Category;
        public string Caption;
        public string Description;

        public LogEntry( string category, string caption, string description )
        {
            this.EventTime = DateTime.Now;
            this.Caption = caption;
            this.Category = category;
            this.Description = description;
        }

        public void Write(ILogListener log)
        {
            if (null != log)
                log.EntryAdded(this);

        }
    }


    public interface ILogListener
    {
        void EntryAdded( LogEntry entry );
    }


    public class ReportingService
    {
        List<ILogListener> logListeners = new List<ILogListener>();

        internal static ReportingService Instance = new ReportingService();

        public static int NumEntriesWritten = 0;

        public static bool HasErrors
        {
            get { return NumEntriesWritten > 0; }
        }

        public static void AddListener(ILogListener eventListener)
        {
            Instance.MethodAddListener(eventListener);
        }

        public static void RemoveListener(ILogListener eventListener)
        {
            Instance.MethodRemoveListener(eventListener);
        }

        public static void WriteEvent(string category, string text)
        {
            LogEntry newEntry = new LogEntry(category, text, "");

            Instance.MethodWriteEvent(newEntry);

            System.Threading.Interlocked.Increment(ref NumEntriesWritten);
        }

        public static void WriteEvent(string category, string text, string detail)
        {
            LogEntry newEntry = new LogEntry(category, text, detail);

            Instance.MethodWriteEvent(newEntry);

            System.Threading.Interlocked.Increment(ref NumEntriesWritten);

        }


        internal void MethodAddListener(ILogListener eventListener)
        {
            lock (logListeners)
                logListeners.Add(eventListener);
        }

        internal void MethodRemoveListener(ILogListener eventListener)
        {
            lock (logListeners)
                logListeners.Remove(eventListener);
        }


        internal void MethodWriteEvent(LogEntry newEntry)
        {
            lock (logListeners)
            {
                foreach (var log in logListeners)
                {
                    try
                    {
                        newEntry.Write(log);
                    }
                    catch { }
                }
           } 
        }
    }


    public class FileLog : ILogListener, IDisposable
    {
        System.IO.StreamWriter writer;

        public FileLog(string path)
            : this(path,false)
        {
        }

        public FileLog(string path, bool appendExisting)
        {

            this.writer = new System.IO.StreamWriter(path, appendExisting);

        }

        #region IDisposable Members

        public void Dispose()
        {
            if (writer != null)
            {
                writer.Flush();
                writer.Close();
                writer = null;
            }

            
        }

        #endregion

        #region ILogListener Members

        public void EntryAdded(LogEntry entry)
        {
            writer.WriteLine(entry.EventTime.ToShortDateString() + "@" + entry.EventTime.ToShortTimeString() + "\t[" + entry.Category + "]\t" + entry.Caption + "\t" + entry.Description);
            writer.Flush();
        }

        #endregion

        public static FileLog CreateNew(string path)
        {
            return new FileLog(path, false);
        }

        public static FileLog Open(string path)
        {
            return new FileLog(path, true);
        }
    }
}
